



#include "efile.h"
#include<string.h>
#include<stdio.h>
/*
typedef struct{    //linked list for the data
    WORD firstBlock;
	WORD lastBlock;
	WORD fileLength;
    char fileName[500];
} FILE_t;

typedef struct{
	BYTE Data[508];
	WORD NextBlock;
} DATABLOCK_t;

typedef union{
	BYTE Data[512];
	DATABLOCK_t DataBlock;
	FILE_t File;
}BLOCK_t;*/

BLOCK_t BLOCK = { {0, } };
BYTE FreeSpace[2048]= {0};
BYTE FreeSlot[2048]= {0};
int CURRENT = -1;
//FILE_t FILE[2048] = { 0, 0, 0, { 0, } };


/*Disk Size in bytes (currently 1MB == 2048 pages (512byte))
18 bytes per file in directory, can have 28 files*/
#define DISKSIZE 1048576
BYTE buff[512]; //datablock chunk to read and write to the SD card
DATABLOCK_t DATABLOCK;
//DIR_t DIR = { 


//---------- eFile_Init-----------------
// Activate the file system, without formating
// Input: none
// Output: 0 if successful and 1 on failure (already initialized)
// since this program initializes the disk, it must run with 
//    the disk periodic task operating      a
int eFile_Init(void){
    int i;
	//eDisk_Init(0);
	
	for(i=0; i < 4; i++){
		eDisk_ReadBlock(BLOCK.Data, i);
		memcpy(&(FreeSpace[512*i]), BLOCK.Data, 512*sizeof(BYTE));
	}
	for(i=4; i < 8; i++){
		eDisk_ReadBlock(BLOCK.Data, i);
		memcpy(&(FreeSlot[512*(i-4)]), BLOCK.Data, 512*sizeof(BYTE));
	}
	return 0;
}; // initialize file system

//---------- eFile_Format-----------------
// Erase all files, create blank directory, initialize free space manager
// Input: none
// Output: 0 if successful and 1 on failure (e.g., trouble writing to flash)
int eFile_Format(void){ 
    int i, result;
	BYTE buf[512] = { 0, };
	for (i = 0; i < 4104; i++) { 
		result = eDisk_WriteBlock (buf, i);
		if (result != 0)
		 	return 1;
		
    }
	return 0;

}; // erase disk, add format

int get_available_file_slot(void){
	int i;
	for(i=0; i<2048; i++){
		if(FreeSlot[i] == 0){
			FreeSlot[i] = 1;
			return i+8;
		}
	}
	return -1;//No free file slots
}

int get_available_data_block(void){
	int i;
	for(i=0; i<2048; i++){
		if(FreeSpace[i] == 0){
			FreeSpace[i] = 1;
			return i+2056;
		}
	}
	return -1;//No free data blocks
}

void free_file_slot(int slot){
	FreeSlot[slot-8]=0;
}
void free_data_block(int block){
	FreeSpace[block-2056] = 0;	
}

void update_directory(void){
	int i;
	for(i=0; i < 4; i++){
		memcpy(BLOCK.Data,&(FreeSpace[512*i]),512*sizeof(BYTE));
		eDisk_WriteBlock(BLOCK.Data, i);
		
	}
	for(i=4; i < 8; i++){
		memcpy(BLOCK.Data,&(FreeSlot[512*(i-4)]), 512*sizeof(BYTE));
		eDisk_WriteBlock(BLOCK.Data, i);
	}
}


//---------- eFile_Create-----------------
// Create a new, empty file with one allocated block
// Input: file name is an ASCII string up to seven characters 
// Output: 0 if successful and 1 on failure (e.g., trouble writing to flash)
int eFile_Create(char name[]){
	int fileslot;
	int firstDataBlock;
	
	fileslot = get_available_file_slot();
	if(fileslot == -1)
		return 1;
	
	firstDataBlock = get_available_data_block();
	if(firstDataBlock == -1){
		free_file_slot(fileslot);
		return 1;
	}
	strcpy(BLOCK.File.fileName, name);
	BLOCK.File.fileLength = 0;
	BLOCK.File.firstBlock = firstDataBlock;
	BLOCK.File.lastBlock = firstDataBlock;
	eDisk_WriteBlock(BLOCK.Data,fileslot);

	eDisk_ReadBlock(BLOCK.Data, firstDataBlock);
	BLOCK.DataBlock.NextBlock = 0;
	eDisk_WriteBlock(BLOCK.Data, firstDataBlock);

	update_directory();

	return 0;
};  // create new file, make it empty 


//---------- eFile_WOpen-----------------
// Open the file, read into RAM last block
// Input: file name is a single ASCII letter
// Output: 0 if successful and 1 on failure (e.g., trouble writing to flash)
int eFile_WOpen(char name[]){
	int i,result;
	for(i=8; i<2056; i++){
		if(FreeSlot[i-8]==1){
			eDisk_ReadBlock(BLOCK.Data, i);
			result = strcmp(BLOCK.File.fileName,name);
			if(result == 0){
				CURRENT = i;
				return 0;
			}
		}
	}
    return 1;
};// open a file for writing 

//---------- eFile_Write-----------------
// save at end of the open file
// Input: data to be saved
// Output: 0 if successful and 1 on failure (e.g., trouble writing to flash)
int eFile_Write(char data){
	int fileSize;
	int lastBlock;
	int newBlock;
	int index;

	eDisk_ReadBlock(BLOCK.Data, CURRENT);
	fileSize = BLOCK.File.fileLength;
	lastBlock = BLOCK.File.lastBlock;
	
	if(fileSize%508 == 0 && fileSize != 0){//last block in file is full
		eDisk_ReadBlock(BLOCK.Data, lastBlock);
		newBlock = get_available_data_block();
		BLOCK.DataBlock.NextBlock = newBlock;	//update ptr for next block
		eDisk_ReadBlock(BLOCK.Data, newBlock);
		BLOCK.DataBlock.NextBlock = 0; 			//make next ptr for this block NULL to signify end of file
		eDisk_ReadBlock(BLOCK.Data, CURRENT);
		BLOCK.File.lastBlock = newBlock;  		//update file info for last block
		lastBlock = BLOCK.File.lastBlock; 
	}
	fileSize = BLOCK.File.fileLength++;
	eDisk_WriteBlock(BLOCK.Data, CURRENT);

	eDisk_ReadBlock(BLOCK.Data, lastBlock);

	index = (fileSize)%508;

	BLOCK.DataBlock.Data[index] = data;

	eDisk_WriteBlock(BLOCK.Data, lastBlock);

	update_directory();

    return 0;

};
  



//---------- eFile_ReadNext-----------------
// retreive data from open file
// Input: none
// Output: return by reference data
//         0 if successful and 1 on failure (e.g., end of file)
int eFile_ReadNext(char *pt){
	int i;
	int fileSize;
	int nextBlock = 0;

	eDisk_ReadBlock(BLOCK.Data, CURRENT);
	fileSize = BLOCK.File.fileLength;
	
	nextBlock =  BLOCK.File.firstBlock;
	eDisk_ReadBlock(BLOCK.Data, nextBlock);
	
	for(i=0; i < fileSize; i++){
		if((fileSize % 508) == 0 && fileSize != 0){
			nextBlock = BLOCK.DataBlock.NextBlock;
			eDisk_ReadBlock(BLOCK.Data, nextBlock);	
		}
		pt[i] = BLOCK.Data[i%508];
	}

    return 0; 

};       // get next byte 
                              


//---------- eFile_Directory-----------------
// Display the directory with filenames and sizes
// Input: pointer to a function that outputs ASCII characters to display
// Output: characters returned by reference
//         0 if successful and 1 on failure (e.g., trouble reading from flash)
int eFile_Directory(char *data){
	int i;
	for(i=8; i<2056; i++){
		if(FreeSlot[i-8]==1){
			eDisk_ReadBlock(BLOCK.Data, i);
			sprintf(data,"%sName: %s\r\n",data,BLOCK.File.fileName);
			sprintf(data,"%sLength: %d\r\n",data,BLOCK.File.fileLength);
		}
	}
    return 0;
};   

//---------- eFile_Delete-----------------
// delete this file
// Input: file name is a single ASCII letter
// Output: 0 if successful and 1 on failure (e.g., trouble writing to flash)
int eFile_Delete( char name[]){
	eFile_WOpen(name);
	free_file_slot(CURRENT);
	update_directory();
    return 0;
};  // remove this file 

//---------- eFile_RedirectToFile-----------------
// open a file for writing 
// Input: file name is a single ASCII letter
// stream printf data into file
// Output: 0 if successful and 1 on failure (e.g., trouble read/write to flash)
int eFile_RedirectToFile(char *name){





    return 0;


};

//---------- eFile_EndRedirectToFile-----------------
// close the previously open file
// redirect printf data back to UART
// Output: 0 if successful and 1 on failure (e.g., wasn't open)
int eFile_EndRedirectToFile(void){

    return 0;


};
